/**
 * 密码加密工具模块
 * 使用bcrypt提供安全的密码哈希和验证功能
 */

import bcrypt from 'bcrypt';

// bcrypt加密轮数（推荐值10，安全性与性能的平衡）
const SALT_ROUNDS = 10;

/**
 * 哈希密码
 * 使用bcrypt算法加密明文密码
 * @param {string} password - 明文密码
 * @returns {Promise<string>} 加密后的密码哈希
 * @throws {Error} 当密码为空或加密失败时抛出错误
 */
export const hashPassword = async (password) => {
  // 参数验证
  if (!password || typeof password !== 'string') {
    throw new Error('Password must be a non-empty string');
  }

  if (password.length < 6) {
    throw new Error('Password must be at least 6 characters long');
  }

  if (password.length > 100) {
    throw new Error('Password is too long (max 100 characters)');
  }

  try {
    // 生成盐值并哈希密码
    const hash = await bcrypt.hash(password, SALT_ROUNDS);
    return hash;
  } catch (error) {
    throw new Error(`Failed to hash password: ${error.message}`);
  }
};

/**
 * 比较密码
 * 验证明文密码与哈希值是否匹配
 * @param {string} password - 明文密码
 * @param {string} hash - 存储的密码哈希
 * @returns {Promise<boolean>} 密码匹配返回true，否则返回false
 * @throws {Error} 当参数无效时抛出错误
 */
export const comparePassword = async (password, hash) => {
  // 参数验证
  if (!password || typeof password !== 'string') {
    throw new Error('Password must be a non-empty string');
  }

  if (!hash || typeof hash !== 'string') {
    throw new Error('Hash must be a valid string');
  }

  // bcrypt哈希值通常以$2a$、$2b$或$2y$开头
  if (!hash.startsWith('$2')) {
    throw new Error('Invalid hash format');
  }

  try {
    // 比较密码
    const isMatch = await bcrypt.compare(password, hash);
    return isMatch;
  } catch (error) {
    throw new Error(`Failed to compare password: ${error.message}`);
  }
};

/**
 * 验证密码强度
 * 检查密码是否符合安全要求
 * @param {string} password - 要验证的密码
 * @returns {Object} 验证结果 { valid: boolean, errors: string[] }
 */
export const validatePasswordStrength = (password) => {
  const errors = [];

  if (!password || typeof password !== 'string') {
    errors.push('密码不能为空');
    return { valid: false, errors };
  }

  // 长度检查
  if (password.length < 6) {
    errors.push('密码长度至少6个字符');
  }

  if (password.length > 100) {
    errors.push('密码长度不能超过100个字符');
  }

  // 基本强度检查（可选，根据需求启用）
  // 注释掉以允许简单密码，如果需要强密码策略可以启用
  
  // if (!/[a-z]/.test(password)) {
  //   errors.push('密码必须包含至少一个小写字母');
  // }

  // if (!/[A-Z]/.test(password)) {
  //   errors.push('密码必须包含至少一个大写字母');
  // }

  // if (!/[0-9]/.test(password)) {
  //   errors.push('密码必须包含至少一个数字');
  // }

  // if (!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password)) {
  //   errors.push('密码必须包含至少一个特殊字符');
  // }

  // 常见弱密码检查
  const weakPasswords = [
    'password',
    '123456',
    '123456789',
    '12345678',
    'qwerty',
    'abc123',
    'password123',
    '111111',
    '123123',
  ];

  if (weakPasswords.includes(password.toLowerCase())) {
    errors.push('密码过于简单，请使用更强的密码');
  }

  return {
    valid: errors.length === 0,
    errors,
  };
};

/**
 * 生成随机密码
 * 用于密码重置或临时密码生成
 * @param {number} length - 密码长度（默认12）
 * @returns {string} 随机生成的密码
 */
export const generateRandomPassword = (length = 12) => {
  const charset =
    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';
  let password = '';

  // 确保至少包含一个小写字母、大写字母、数字和特殊字符
  password += 'abcdefghijklmnopqrstuvwxyz'.charAt(
    Math.floor(Math.random() * 26)
  );
  password += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.charAt(
    Math.floor(Math.random() * 26)
  );
  password += '0123456789'.charAt(Math.floor(Math.random() * 10));
  password += '!@#$%^&*'.charAt(Math.floor(Math.random() * 8));

  // 填充剩余字符
  for (let i = password.length; i < length; i++) {
    password += charset.charAt(Math.floor(Math.random() * charset.length));
  }

  // 打乱顺序
  return password
    .split('')
    .sort(() => Math.random() - 0.5)
    .join('');
};

export default {
  hashPassword,
  comparePassword,
  validatePasswordStrength,
  generateRandomPassword,
};

